home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Copyright (c) 1991 Bolt Beranek and Newman, Inc.
- ** All rights reserved.
- **
- ** Redistribution and use in source and binary forms are permitted
- ** provided that: (1) source distributions retain this entire copyright
- ** notice and comment, and (2) distributions including binaries display
- ** the following acknowledgement: ``This product includes software
- ** developed by Bolt Beranek and Newman, Inc. and CREN/CSNET'' in the
- ** documentation or other materials provided with the distribution and in
- ** all advertising materials mentioning features or use of this software.
- ** Neither the name of Bolt Beranek and Newman nor CREN/CSNET may be used
- ** to endorse or promote products derived from this software without
- ** specific prior written permission.
- **
- ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
- ** WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
- #include <stdio.h>
- #include <signal.h>
- #include <errno.h>
- #include <setjmp.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- #include <sys/ioctl.h>
- #include <sys/time.h>
- #include <sys/file.h>
- #include <sys/param.h>
- #include <netinet/in.h>
- #include <netinet/in_systm.h>
- #include <netinet/ip.h>
- #include <sys/socket.h>
- #include <net/if.h>
- #include <net/if_du.h>
- #include "dialupip.h"
- #include "diald.h"
-
- typedef struct _TABLE {
- int Protocol;
- char *Name;
- } TABLE;
-
-
- static jmp_buf context;
- static int pleaserescan;
- static int pleasequit;
- static char *WHERE = "diald";
- static TABLE ProtocolNames[] = {
- #ifdef IPPROTO_IP
- { IPPROTO_IP, "IP Dummy" },
- #endif
- #ifdef IPPROTO_ICMP
- { IPPROTO_ICMP, "ICMP" },
- #endif
- #ifdef IPPROTO_GGP
- { IPPROTO_GGP, "GGP" },
- #endif
- #ifdef IPPROTO_TCP
- { IPPROTO_TCP, "TCP" },
- #endif
- #ifdef IPPROTO_EGP
- { IPPROTO_EGP, "EGP" },
- #endif
- #ifdef IPPROTO_PUP
- { IPPROTO_PUP, "PUP" },
- #endif
- #ifdef IPPROTO_UDP
- { IPPROTO_UDP, "UDP" },
- #endif
- #ifdef IPPROTO_IDP
- { IPPROTO_IDP, "IDP" },
- #endif
- #ifdef IPPROTO_RAW
- { IPPROTO_RAW, "RAW" },
- #endif
- { 0, NULL }
- };
-
-
-
- static int
- authorized(rp, pkt)
- register REMOTE *rp;
- register struct du_pkt *pkt;
- {
- register int i;
- register TABLE *tp;
- struct timeval tv;
- struct tm *tm;
-
- /* check protocol */
- i = pkt->du_ip.ip_p;
- if ((rp->Protocols[P_WORD(i)] & P_BIT(i)) == 0) {
- for (tp = ProtocolNames; tp->Name; tp++)
- if (i == tp->Protocol)
- break;
- d_log(DLOG_INFO, WHERE, "Bad protocol %s (%d)",
- tp ? tp->Name : "unknown");
- return 0;
- }
-
- /* Check time. */
- if (gettimeofday(&tv, (struct timezone *)NULL) < 0) {
- d_log(DLOG_GENERAL, WHERE, "Can't do gettimeofday, %m");
- return 0;
- }
- if ((tm = localtime(&tv.tv_sec)) == NULL) {
- d_log(DLOG_GENERAL, WHERE, "Can't do localtime, %m");
- return 0;
- }
- if ((rp->Times[tm->tm_wday] & (1L << tm->tm_hour)) == 0) {
- d_log(DLOG_INFO, WHERE, "Bad time to call");
- return 0;
- }
-
- /* Check addresses. */
- if (rp->AllowCount && !hostinlist(rp->AllowTo, pkt->du_ip.ip_dst)) {
- d_log(DLOG_INFO, WHERE, "Bad destination address \"%s\"",
- inet_ntoa(pkt->du_ip.ip_dst));
- return 0;
- }
- if (rp->DisallowCount && hostinlist(rp->DisallowFrom, pkt->du_ip.ip_src)) {
- d_log(DLOG_INFO, WHERE, "Bad source address \"%s\"",
- inet_ntoa(pkt->du_ip.ip_src));
- return 0;
- }
-
- /* o.k. to make call */
- return 1;
- }
-
-
- static void
- catchsigterm()
- {
- pleasequit++;
- longjmp(context, 1);
- }
-
-
- static void
- catchsighup()
- {
- pleaserescan++;
- (void)signal(SIGHUP, catchsighup);
- longjmp(context, 1);
- }
-
-
- static void
- catchsigchld()
- {
- union wait wstatus;
-
- while (wait3(&wstatus, WNOHANG, (struct rusage *)NULL) > 0)
- ;
- }
-
-
-
- static void
- usage()
- {
- (void)fprintf(stderr, "usage: %s [options]\n", progname);
- d_log(DLOG_GENERAL, WHERE, "Usage error");
- exit(1);
- }
-
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int f;
- int dofork;
- int i;
- struct du_pkt pkt;
- REMOTE *rp;
- char buff[256];
- char *configfile;
-
- /* Set defaults. */
- setprogname(argv[0]);
- WHERE = progname;
- dofork = 1;
- configfile = DIALD_CONFIG;
-
- /* Parse flags. */
- while ((i = getopt(argc, argv, "c:d:F")) != EOF)
- switch (i) {
- default:
- usage();
- /* NOTREACHED */
- case 'c':
- configfile = optarg;
- break;
- case 'd':
- log_level = atoi(optarg);
- break;
- case 'F':
- dofork = 0;
- break;
- }
- argc -= optind;
- argv += optind;
- if (argc)
- usage();
-
- /* Fork us off */
- if (dofork) {
- if ((i = fork()) < 0) {
- d_log(DLOG_GENERAL, WHERE, "Can't fork, %m");
- exit(1);
- }
- if (i > 0)
- exit(0);
- if (freopen("/dev/console", "w", stderr) == NULL)
- d_log(DLOG_GENERAL, WHERE, "Can't set stderr to /dev/console, %m");
- }
-
- /* Read configuration data. */
- if (!readconfig(configfile))
- exit(1);
-
- /* Open the request device. */
- if ((f = open(DEVDIAL, O_RDONLY)) < 0) {
- d_log(DLOG_GENERAL, WHERE, "Can't open \"%s\", %m", DEVDIAL);
- exit(1);
- }
- #ifdef FIOCLEX
- if (ioctl(f, FIOCLEX, (caddr_t)NULL) < 0)
- d_log(DLOG_INFO, WHERE, "Can't do FIOCLEX on \"%s\", %m", DEVDIAL);
- #endif /* FIOCLEX */
-
- /* Tell the log file where are here */
- d_log(DLOG_GENERAL, WHERE, "Diald %s started", dip_release());
- (void)record_pid(progname);
-
- /* Process requests */
- (void)signal(SIGHUP, catchsighup);
- (void)signal(SIGTERM, catchsigterm);
- (void)signal(SIGCHLD, catchsigchld);
- for ( ; ; ) {
- (void)setjmp(context);
- if (pleasequit)
- break;
- if (pleaserescan) {
- d_log(DLOG_GENERAL, WHERE, "Rescanning config files");
- if (!readconfig(configfile)) {
- unlock_pid();
- exit(1);
- }
- (void)signal(SIGHUP, catchsighup);
- pleaserescan = 0;
- continue;
- }
-
- /* Read the device. */
- if ((i = read(f, (char *)&pkt, sizeof pkt)) != sizeof pkt) {
- if (errno != EINTR)
- d_log(DLOG_GENERAL, WHERE,
- "Bad read (%d bytes) from \"%s\", %m",
- i, DEVDIAL);
- continue;
- }
-
- /* Find config data for the address. */
- (void)sprintf(buff, "%s%d", pkt.du_ifname, pkt.du_ifunit);
- if ((rp = findconfig(buff)) == NULL) {
- d_log(DLOG_GENERAL, WHERE, "Address %s not configured",
- inet_ntoa(pkt.du_sin.sin_addr));
- continue;
- }
-
- /* Is this packet is authorized? */
- if (pkt.du_checkit && !authorized(rp, &pkt)) {
- (void)sprintf(buff, "%s not authorized to reach %s",
- inet_ntoa(pkt.du_ip.ip_src), inet_ntoa(pkt.du_ip.ip_dst));
- failcall(rp->Device, buff);
- continue;
- }
-
- /* Make the call. */
- if (!dofork) {
- makecall(rp);
- continue;
- }
- if ((i = fork()) == 0) {
- (void)setpgrp(0, getpgrp(0));
- makecall(rp);
- break;
- }
- if (i < 0)
- d_log(DLOG_GENERAL, WHERE, "Can't fork dialing process, %m");
- }
-
- d_log(DLOG_GENERAL, WHERE, "Diald %s exiting", dip_release());
- unlock_pid();
- exit(0);
- /* NOTREACHED */
- }
-